package org.seaurchin.parser;

import org.seaurchin.database.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;


public class Parser {

	//No generics
	List <SiteInfo> mySiteInfo;
	List <PublisherInfo> myPublisher;
	List <SiteCategories> myCategories;
	Document dom;


	public Parser(){
		myPublisher = new ArrayList<PublisherInfo>();
		myCategories = new ArrayList<SiteCategories>();
		mySiteInfo = new ArrayList<SiteInfo>();
	}

	public void runExample(String filePath) {
		parseXmlFile(filePath);
		parseDocument();
		storeData();
	}
	
	
	private void parseXmlFile(String filePath){
		//get the factory
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		
		try {
			
			//Using factory get an instance of document builder
			DocumentBuilder db = dbf.newDocumentBuilder();
			
			//parse using builder to get DOM representation of the XML file
//			dom = db.parse("SiteInfo.xml");
			dom = db.parse(filePath);
			

		}catch(ParserConfigurationException pce) {
			pce.printStackTrace();
		}catch(SAXException se) {
			se.printStackTrace();
		}catch(IOException ioe) {
			ioe.printStackTrace();
		}
	}

	
	private void parseDocument(){
		//get the root elememt
		Element docEle = dom.getDocumentElement();
		
		//get a nodelist of PublisherInfo elements
		NodeList nlPI = docEle.getElementsByTagName("PublisherInfo");
		if(nlPI != null && nlPI.getLength() > 0) {
			for(int i = 0 ; i < nlPI.getLength();i++) {
				
				//get the element
				Element el = (Element)nlPI.item(i);
				
				//get the object
				PublisherInfo e = getPublisherInfo(el);
				
				//add it to list
				myPublisher.add(e);
			}
		}
		
		//get a nodelist of Entry elements
		NodeList nlE = docEle.getElementsByTagName("Entry");
		if(nlE != null && nlE.getLength() > 0) {
			for(int i = 0 ; i < nlE.getLength();i++) {
				
				//get the element
				Element el = (Element)nlE.item(i);
				
				//get the object
				SiteInfo e = getSiteInfo(el);
				
				//add it to list
				mySiteInfo.add(e);
			}
		}
		
		//Site Category data is at the root so handle differently
		SiteCategories e = getSiteCategories(docEle);
		myCategories.add(e);
	}


	private SiteInfo getSiteInfo(Element siteInfo) {
		String name = getTextValue(siteInfo, "Name");
		String description = getTextValue(siteInfo, "Description");
		String service_type = getTextValue(siteInfo, "ServiceType");
		String service_url = getTextValue(siteInfo, "ServiceUrl");
		String access_info = getTextValue(siteInfo, "AccessInfo");
		
		SiteInfo e = new SiteInfo(name, description, service_type, service_url, access_info);
		
		return e;
	}

	private PublisherInfo getPublisherInfo(Element pubInfo) {
		String contact_name = getTextValue(pubInfo, "ContactName");
		String title = getTextValue(pubInfo, "Title");
		String affiliation = getTextValue(pubInfo, "Affiliation");
		String phone = getTextValue(pubInfo, "Phone");
		String email = getTextValue(pubInfo, "Email");
		
		PublisherInfo e = new PublisherInfo(contact_name, title, affiliation, phone, email);
		
		return e;
	}

	private SiteCategories getSiteCategories(Element categInfo) {
		String name = getTextValue(categInfo, "Name");
		String category = getTextValue(categInfo, "Category");
		String taxonomyschema = getTextValue(categInfo, "TaxonomySchema");
		
		SiteCategories e = new SiteCategories(name, category, taxonomyschema);
		
		return e;
	}

	private String getTextValue(Element ele, String tagName) {
		String textVal = null;
		NodeList nl = ele.getElementsByTagName(tagName);
		if(nl != null && nl.getLength() > 0) {
			Element el = (Element)nl.item(0);
			textVal = el.getFirstChild().getNodeValue();
		}

		return textVal;
	}

	private int getIntValue(Element ele, String tagName) {
		return Integer.parseInt(getTextValue(ele,tagName));
	}
	
	/**
	 * Iterate through the lists and store the site info contents to the seaurchin db
	 */
	private void storeData(){
		persist.BeginTrans();
		
		System.out.println("No of SiteInfos '" + mySiteInfo.size() + "'.");
		
		Iterator it3 = mySiteInfo.iterator();
		while(it3.hasNext()) {
			System.out.println("Storing Site Info");
			persist.StoreSiteInfo((SiteInfo) it3.next());
		}

		System.out.println("No of Publishers '" + myPublisher.size() + "'.");
		
		Iterator it = myPublisher.iterator();
		while(it.hasNext()) {
			System.out.println("Storing Publisher Info");
			persist.StorePublisherInfo((PublisherInfo) it.next());
		}
		
		System.out.println("No of Categories '" + myCategories.size() + "'.");
		
		Iterator it2 = myCategories.iterator();
		while(it2.hasNext()) {
			System.out.println("Storing Category");
			persist.StoreSiteCategories((SiteCategories) it2.next());
		}
		persist.CommitTrans();
	}
	
	
	public static void main(String[] args){
		//create an instance
		Parser dpe = new Parser();
		
		dpe.runExample(args[0]);
	}

}
